package com.xuecheng.auth.domain.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.xuecheng.auth.domain.model.dto.XcUserDto;
import com.xuecheng.auth.domain.model.entity.XcUser;
import com.xuecheng.auth.domain.model.vo.req.AuthParamsQuery;
import com.xuecheng.auth.domain.model.vo.req.WxLoginQry;
import com.xuecheng.auth.domain.service.WxLoginService;
import com.xuecheng.auth.domain.service.XcUserService;
import com.xuecheng.auth.domain.strategy.AuthContext;
import com.xuecheng.base.exception.XueChengPlusException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @Author: LiJunXi
 * @Description:
 * @Date: 2024-09-08  15:24
 */
@Service
public class WxLoginServiceImpl implements WxLoginService {

    @Autowired
    private RestTemplate restTemplate;

    private String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code";
    private String USERINFO_URL = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s";

    @Value("${wechat.appid}")
    private String appid;

    @Value("${wechat.secret}")
    private String secret;

    @Override
    public String wxLogin(WxLoginQry wxLoginQry) {
        // 封装参数
        AuthParamsQuery params = new AuthParamsQuery();
        Map<String, Object> map = BeanUtil.beanToMap(wxLoginQry);
        map.put("appid", appid);
        map.put("secret", secret);
        params.setAuthType("wx");
        params.setPayload(map);

        XcUserDto xcUserDto = getUserDto(params);

        if (Objects.isNull(xcUserDto)){
            return "redirect:http://www.51xuecheng.cn/error.html";
        }
        return "redirect:http://www.51xuecheng.cn/sign.html?username=" + xcUserDto.getUsername() + "&authType=wx";
    }

    @Transactional
    public XcUserDto getUserDto(AuthParamsQuery params) {
        // 根据appid、secret和code获取access_token
        Map<String, String> map = getAccessTokenResult(params);
        if (Objects.isNull(map) || map.isEmpty()){
            throw new XueChengPlusException("请求access_token出错");
        }
        // 根据access_token获取用户信息
        Map<String, String> userinfo = getUserInfo(map.get("access_token"), map.get("openid"));
        if (Objects.isNull(userinfo) || userinfo.isEmpty()){
            throw new XueChengPlusException("请求用户信息出错");
        }

        XcUser xcUser = XcUser.buildByWechat(userinfo);
        XcUserService xcUserService = SpringUtil.getBean("xcUserServiceImpl");
        XcUser findUser = xcUserService.getByUsername(xcUser.getUsername());
        if (Objects.isNull(findUser)){
            // 未存在就直接保存
            xcUserService.save(xcUser);
        }
        //todo 保存用户角色


        return BeanUtil.copyProperties(xcUser, XcUserDto.class);
    }

    private Map<String, String> getUserInfo(String accessToken, String openid) {
        String userUrl = String.format(USERINFO_URL, accessToken, openid);
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(userUrl, HttpMethod.POST, String.class);

        return JSONUtil.toBean(responseEntity.getBody(), Map.class);
    }

    private Map<String, String> getAccessTokenResult(AuthParamsQuery params) {
        // 获取请求地址
        String accessTokenUrl = String.format(ACCESS_TOKEN_URL, params.getPayload().get("appid")
                , params.getPayload().get("secret"), params.getPayload().get("code"));
        // 发送请求
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(accessTokenUrl, HttpMethod.POST, String.class);

        return JSONUtil.toBean(responseEntity.getBody(), Map.class);
    }
}


